#define LOG_TAG "adc.tag"
#include "temp_det.h"
#include "elog.h"

#include "stm32mp1xx_hal.h"

#include "FreeRTOS.h"
#include "task.h"

#include <math.h>

extern rt_adc_device_t adc;
static double ch1_temp, ch2_temp;

/**
 * @brief NTC阻值表
 */
static const ntc_tab_t ntc_tab[] = {
    {-40, 302.800}, {-39, 288.388}, {-38, 273.878}, {-37, 259.472}, {-36, 245.341},
    {-35, 231.621}, {-34, 218.414}, {-33, 205.792}, {-32, 193.798}, {-31, 182.455},
    {-30, 171.765}, {-29, 161.719}, {-28, 152.296}, {-27, 143.472}, {-26, 135.214},
    {-25, 127.490}, {-24, 120.264}, {-23, 113.504}, {-22, 107.177}, {-21, 101.252},
    {-20, 95.698}, {-19, 90.488}, {-18, 85.597}, {-17, 81.002}, {-16, 76.681},
    {-15, 72.615}, {-14, 68.785}, {-13, 65.176}, {-12, 58.561}, {-11, 58.561},
    {-10, 52.667}, {-9, 52.667}, {-8, 49.962}, {-7, 47.406}, {-6, 44.990},
    {-5, 40.545}, {-4, 40.545}, {-3, 38.501}, {-2, 36.568}, {-1, 34.740},
};

/**
 * @brief                   二分法查表
 * @param  ptr              指向表的指针
 * @param  table_size       表的大小
 * @param  data             目标数据
 * @return uint8_t          目标数据索引
 */
static uint8_t lookup_tab(const ntc_tab_t *const ptr, uint8_t table_size, float data)
{
    uint16_t begin = 0; uint16_t end = 0; 
    uint16_t middle = 0; uint8_t i = 0;
    end = table_size - 1;

    if (data > ptr[begin].r)
        return begin;
    else if (data < ptr[end].r)
        return end;

    while (begin < end) {
        middle = (begin + end) >> 1;
        if (fabs(data - ptr[middle].r) < 1e-7)
            break;
        if (data < ptr[middle].r && data > ptr[middle + 1].r)
            break;
        if (data > ptr[middle].r)
            end = middle;
        else
            begin = middle;
        if (i++ > table_size)
            break;
    }
    
    if (begin > end)
        return 0;

    return middle;
}

/**
 * @brief 温度检测公式       	AD值大于2048正温度系数，零上温度 ：vth = (3.3 * (1000 + 3.856 * tth))/(2000 + 3.856 * tth)
 *                          AD值小于2048负温度系数，零下温度 ：vtl = (3.3 * (1000 + 3.979 * ttl))/(2000 + 3.979 * ttl)
 */
/**
 * @brief                   获取系统各部件温度数据
 * @param  chn              测温通道
 * @param  ad_value         滤波之后的AD值      
 * @return float 
 */
double pt1000_temp_poll(int chn)
{
    int ret = 0;
    static uint32_t ch1_value = 0, ch2_value = 0;
    static int ch1_i = 0, ch2_i = 0;
    static double ch1_vol = 0.0f;
    static double ch2_vol = 0.0f;

    switch (chn)
    {
    case 0:
        rt_adc_enable(adc, TEMP_CH1);
        ch1_value += rt_adc_read(adc, TEMP_CH1);
        ch1_i++;
        if (ch1_i >= 10) {

            ch1_i = 0;
            ch1_value /= 10;
            ch1_vol = ((double)ch1_value / TEMP_CONVERT_BITS) * TEMP_REFER_VOLTAGE;
            if (ch1_value >= 2048) {
                /* 计算通道1的温度 */
                ch1_temp = (ch1_vol * 2000 - 3300) / (12.7248 - 3.856 * ch1_vol);
                log_d("adc > 2048 %d, vol %d, ch1 temp %d", ch1_value, (uint32_t)(ch1_vol * 100), (int32_t)(ch1_temp * 100));
                ch1_value = 0;
            }
            else {
                ch1_temp = (ch1_vol * 2000 - 3300) / (13.1307 - 3.979 * ch1_vol);
                log_d("adc < 2048 %d, vol %d, ch1 temp %d", ch1_value, (uint32_t)(ch1_vol * 100), (int32_t)(ch1_temp * 100));
                ch1_value = 0;
            }
        }
        break;
    case 1:
        rt_adc_enable(adc, TEMP_CH2);
        ch2_value += rt_adc_read(adc, TEMP_CH2);
        ch2_i++;
        if (ch2_i >= 10) {
            ch2_i = 0;
            ch2_value /= 10;
            /* 计算通道2的温度 */
            ch2_vol = ((double)ch2_value / TEMP_CONVERT_BITS) * TEMP_REFER_VOLTAGE;
            if (ch2_value >= 2048) {
                ch2_temp = (ch2_vol * 2000 - 3300) / (12.7248 - 3.856 * ch2_vol);
                log_d("adc > 2048 %d, vol %d, ch2 temp %d", ch2_value, (uint32_t)(ch2_vol * 100), (int32_t)(ch2_temp * 100));
                ch2_value = 0;
            }
            else {
                ch2_temp = (ch2_vol * 2000 - 3300) / (13.1307 - 3.979 * ch2_vol);
                log_d("adc < 2048 %d, vol %d, ch2 temp %d", ch2_value, (uint32_t)(ch2_vol * 100), (int32_t)(ch2_temp * 100));
                ch2_value = 0;
            }
        }
        break;
    default:
        break;
    }
    return ret;
}

double ntc_temp_poll(int chn)
{
    int ret = 0;
    int index = 0;
    double ntc_r = 0.0f;
    static uint32_t ch1_value = 0, ch2_value = 0;
    static int ch1_i = 0, ch2_i = 0;
    static double ch1_vol = 0.0f;
    static double ch2_vol = 0.0f;

    switch (chn)
    {
    case 0:
        rt_adc_enable(adc, TEMP_CH1);
        ch1_value += rt_adc_read(adc, TEMP_CH1);
        ch1_i++;
        if (ch1_i >= 10) {

            ch1_i = 0;
            ch1_value /= 10;
            /* 计算通道1的温度 */
            ch1_vol = ((double)ch1_value / TEMP_CONVERT_BITS) * TEMP_REFER_VOLTAGE;
            // ntc_r = (double)(((ch1_vol * NTC_DR) / (NTC_VOL - ch1_vol)) / 1000);       /* 换算成千欧 */
            ntc_r = (double)(CALCULATE_NTC_R(ch1_vol, NTC_VOL, NTC_DR) / 1000);
            index = lookup_tab((ntc_tab_t *)ntc_tab, sizeof(ntc_tab)/sizeof(ntc_tab_t), ntc_r);
            ch1_temp = ntc_tab[index].temp;
        }
        break;
    case 1:
        rt_adc_enable(adc, TEMP_CH2);
        ch2_value += rt_adc_read(adc, TEMP_CH2);
        ch2_i++;
        if (ch2_i >= 10) {
            ch2_i = 0;
            ch2_value /= 10;
            /* 计算通道2的温度 */
            ch2_vol = ((double)ch2_value / TEMP_CONVERT_BITS) * TEMP_REFER_VOLTAGE;
            // ntc_r = (double)(((ch2_vol * NTC_DR) / (NTC_VOL - ch2_vol)) / 1000);       /* 换算成千欧 */
            ntc_r = (double)(CALCULATE_NTC_R(ch2_vol, NTC_VOL, NTC_DR) / 1000);
            index = lookup_tab((ntc_tab_t *)ntc_tab, sizeof(ntc_tab)/sizeof(ntc_tab_t), ntc_r); 
            ch2_temp = ntc_tab[index].temp;   
        }
        break;
    default:
        break;
    }
    return ret;
}

/**
 * @brief Get the ch1 temp object
 * @return double 
 */
double get_ch1_temp(void)
{
    return ch1_temp;
}

/**
 * @brief Get the ch2 temp object
 * @return double 
 */
double get_ch2_temp(void)
{
    return ch2_temp;
}
